import data from "../../../../core/cache_data";
import { ReplacePageAni } from "../../../../core/game";
import SerializeAble, { Serialize, SerializeClass } from "../../../../core/serialize";
import { SubjectComponent } from "../../../../core/subject";
import Utils, { Sync } from "../../../../core/utils";
import WorldEdge from "../../../box2d_utils/world_edge";
import Ball from "./ball";
import PlayerArea, { PlayerData } from "./player_area";

const { ccclass, property } = cc._decorator;

@SerializeClass("PingPongGameConfig")
export class PingPongGameConfig extends SerializeAble {
    @Serialize()
    speedLimitation = true;
    @Serialize()
    limitSpeed = 1800;
    @Serialize()
    doorSize = 250;
    @Serialize()
    handleSize = 250;
    @Serialize()
    healthMax = 5;
};
@ccclass
export default class PageGame extends SubjectComponent {
    areas: PlayerArea[] = [];

    @property(cc.Prefab)
    tablePrefab: cc.Prefab = null;
    @property(cc.Camera)
    wCam: cc.Camera = null;
    table: cc.Node = null;

    @property(cc.Node)
    root: cc.Node = null;

    @property(cc.Prefab)
    ballPrefab: cc.Prefab = null;
    ball: cc.Node = null;

    config: PingPongGameConfig = null;

    playerDatas: PlayerData[] = [];
    protected onDisable(): void {
        cc.director.getPhysicsManager().enabled = false;
        Utils.game.sceneCamera.enabled = true;
    }
    protected onEnable(): void {
        Utils.game.sceneCamera.enabled = false;
        let mgr = cc.director.getPhysicsManager();
        mgr.enabled = true;
        mgr.gravity = cc.v2();
        // mgr.debugDrawFlags = cc.PhysicsManager.DrawBits.e_shapeBit;
    }

    protected onDestroy(): void {
        if (cc.isValid(this.table)) {
            this.table.destroy();
            this.table = null;
        }
    }

    protected onLoad(): void {
        this.config = data.cache.get<PingPongGameConfig>("ping-pong-game-config");

        this.playerDatas = [];
        for (let i = 0; i < 2; i++) {
            let dat = new PlayerData();
            dat.health = this.config.healthMax;
            this.playerDatas.push(dat);
        }
    }
    async start() {
        await Sync.DelayTime(1.0);
        //一定要在start中调用，因为要先等box2d world创建
        this.table = cc.instantiate(this.tablePrefab);
        this.table.height = this.node.height;
        let edge = this.table.getComponentInChildren(WorldEdge);
        edge.node.height = this.node.height + 200;
        edge.updateEdge();
        this.root.addChild(this.table);

        this.areas = this.table.getComponentsInChildren(PlayerArea);

        this.updateConfig();

        await Sync.DelayTime(1.0);
        this.spawnBall();
    }

    updateConfig() {
        this.areas.forEach((area, ind) => {
            area.init(this.playerDatas[ind]);
            area.on("ball-in", this.onBallIn, this);
            area.on("dead", this.onPlayerDead, this);
            area.setDoorSize(this.config.doorSize);
            area.setHandleSize(this.config.handleSize);
        });
        if (this.ball) {
            let ball = this.ball.getComponent(Ball);
            ball.speedLimitation = this.config.speedLimitation;
            ball.limitSpeed = this.config.limitSpeed;
        }
    }
    async onBallIn() {
        if (!cc.isValid(this) || !cc.isValid(this.ball)) {
            return;
        }

        this.ball.destroy();
        this.ball = null;

        await Sync.DelayTime(1.0);
        this.spawnBall();
    }

    spawnBall() {
        this.ball = cc.instantiate(this.ballPrefab);
        let ball = this.ball.getComponent(Ball);
        ball.speedLimitation = this.config.speedLimitation;
        ball.limitSpeed = this.config.limitSpeed;
        this.table.addChild(this.ball);
    }
    async onPlayerDead() {
        await Utils.game.msgBoxSync("游戏结束");
        this.node.destroy();
        await Sync.DelayTime(0.5);
        Utils.game.resReplacePage({
            name: "page_game",
            ani: ReplacePageAni.None
        });
    }

    async onClickReset() {
        this.node.destroy();
        await Sync.DelayTime(0.5);
        Utils.game.resReplacePage({
            name: "page_setup",
            ani: ReplacePageAni.None
        });
    }
};